#include <stdio.h>
#include <stdlib.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include "../Includes/Driver.h"
#include <string.h>
#include <fcntl.h>

/// <summary>
/// Locals
/// </summary>
int drm = -1;
drm_magic_t	magic;
drmVersionPtr drmlibv;
static const char device_name[] = "/dev/dri/card0";
drmServerInfo server = {
	.debug_print = DRMDebugPrint,
	.load_module = DRMLoadModule,
	.get_perms = NULL
};

/// <summary>
/// TODO
/// </summary>
int DRMOpen(void)
{
	int i = 0;

	if (FBDOpen() < 0)
		return -1;

	if ((drm = open(device_name, O_RDWR)) < 0)
		return -1;

	if (drmSetMaster(drm))
		return -1;

	drmSetServerInfo(&server);
	
	/*
	drm_context_t ctx;
	drmError(drmCreateContext(drm, &ctx), ":__");
	
	drmModeConnectorPtr con;
	if ((con = drmModeGetConnector(drm, 0))) {
		printf("CON: %d\n", con->mmWidth);
	}
*/
	drmModeRes *resources;
	resources = drmModeGetResources(drm);
	if (!resources) {
		fprintf(stderr, "drmModeGetResources failed\n");
		return -1;
	}

	printf("Connectors:\n");	
	printf("\tCount: %d\n", resources->count_connectors);	
	for (i = 0; i < resources->count_connectors; i++)
	{
		drmModeConnector *connector;
		connector = drmModeGetConnector(drm, resources->connectors[i]);
		if (connector == NULL)
			continue;
		printf("CON: %d\n", connector->connection);
		drmModeFreeConnector(connector);
	}
  
	printf("FBO:\n");	
	printf("\tCount: %d\n", resources->count_fbs);	
   	for (i = 0; i < resources->count_fbs; i++)
	{
		drmModeFBPtr fbo;
		fbo = drmModeGetFB(drm, resources->fbs[i]);
		if (fbo == NULL)
			continue;

		printf("FBO:\n");		
		printf("Width: %d\n", fbo->width);
		printf("Height: %d\n", fbo->height);

		drmModeFreeFB(fbo);
	}

//	drm_drawable_t handle;
//	drmError(drmCreateDrawable(drm, &handle), ":__");

	return 0;
}

/// <summary>
/// TODO
/// </summary>
int DRMInitFramebuffers(void)
{
	int i = 0;
	int mtrr;
	drmSize size;
	drmMapType type;
	drmMapFlags flags;
	drm_handle_t handle;
	drm_handle_t offset;

	for (i = 0; ; i++) {
		if (drmGetMap(drm, i, &offset, &size, &type, &flags, &handle, &mtrr))
			break;	
	}
	return 0;
}

/// <summary>
/// TODO
/// </summary>
int DRMCreateSurface(void)
{
	SurfacePtr win;
	if (!(win = (SurfacePtr)malloc(sizeof(Surface))))
		return -1;

	return 0;
}

/// <summary>
/// TODO
/// </summary>
int DRMDestroySurface(SurfacePtr surface)
{
	if (surface == NULL)
		return -1;
	return 0;
}

/// <summary>
/// TODO
/// </summary>
int DRMCreateFramebuffer(FramebufferPtr fbo)
{
	if (FBDCreateFramebuffer(fbo) < 0)
		return -1;

	drm_handle_t handle;
	if (drmAddMap(drm, fbo->start, fbo->len, DRM_FRAME_BUFFER, 0, &handle))
		printf("CreateFramebuffer\n");

	//if (fbo->base != NULL)
	//	memset(fbo->base, 200, 200000);
		
	//unsigned char* ptr = (unsigned char*)fbo->base;

	// In den Framebuffer-Speicher schreiben. Hier wird Pixel fuer Pixel auf 
	// die Farbe 0x01 (Blau) gesetzt   
   //for(row = 0; row < fbo->height - 1; row++) 
    // for(col = 0; col < fbo->width; col++) 
     //   ptr[row * fbo->width + col] = 0x01;
	return 0;
}

/// <summary>
/// TODO
/// </summary>
int DRMClose(void) {
	return 0;
}

/// <summary>
/// TODO
/// </summary>
int DRMInit(DriverPtr drv)
{
	if (drv == NULL)
		return -1;

	if (!drmAvailable())
		return -1;

	drv->state = 0;
	drv->name = "DRM Driver";
	drv->Open = DRMOpen;
	drv->CreateSurface = DRMCreateSurface;
	drv->DestroySurface = DRMDestroySurface;
	drv->CreateFramebuffer = DRMCreateFramebuffer;

	drmlibv = drmGetLibVersion(-1);
	if (drmlibv != NULL) {
		printf("Driver: %s\n", drmlibv->name);
		printf("Version: %d\n", drmlibv->version_major);
	    drmFreeVersion(drmlibv);
	}
	
	return 0;
}

/// <summary>
/// TODO
/// </summary>
int DRMLoadModule(const char *name)
{
	printf(name);
	printf("_____________________");
	return 0;
}

/// <summary>
/// TODO
/// </summary>
int DRMDebugPrint(const char *format, va_list ap)
{
	return vfprintf(stderr, format, ap);
}
